package org.example.project.common.error.handle;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.example.project.common.error.util.ErrorHandleUtils;
import org.example.project.common.util.AspectLogUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * 服务层日志切面
 * <p>
 * 1. 拦截业务处理异常
 * 2. 返回B类异常
 * ×    2.1 对于C类异常，直接抛出不记录
 * ×    2.2 记录日志，封装B类异常返回
 *
 * @author wenxy
 * @date 2020/10/26
 */
@Component
@Aspect
@Slf4j
public class ServiceLogAspect {

    /**
     * 启停切面
     * 通过属性有2种方式，
     * 1. 是通过属性@ConditionalOnProperty，控制切面bean
     * 2. 增加变量
     */
    @Value("${yundasys.vienna.common.service-log.enable:true}")
    boolean enable;

    @Pointcut("execution(* com.yundasys..*ServiceImpl.*(..))")
    public void pointCut() {
    }

    /**
     * service正常方法出入口信息仅debug级别（开发测试开启）
     *
     * @param joinPoint 切点
     * @param result    响应结果
     */
    @AfterReturning(pointcut = "pointCut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        if (isEnable() && log.isDebugEnabled()) {
            log.debug(AspectLogUtils.buildLog(joinPoint, result).toString());
        }
    }

    /**
     * service无法捕捉所有异常（web层异常等），
     * 附加异常方法出入口信息，重新抛出
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(pointcut = "pointCut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        if (isEnable()) {
            ErrorHandleUtils.handleServiceException(joinPoint, e, log);
        }
    }

    boolean isEnable() {
        return enable;
    }

}
